package com.evil.kingdom.pojo.entity.action;

import cn.hutool.core.lang.UUID;
import com.evil.kingdom.pojo.entity.base.Fight;
import com.evil.common.mongo.entity.SingleName;
import com.evil.kingdom.pojo.enums.result.RCodeEnum;
import com.evil.kingdom.task.timer.AttackTimerTask;
import com.evil.kingdom.utils.DijkstraUtil;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;

/**
 * 战斗-个人版
 *
 * @author liyang
 * @date 2024-06-25 11:02
 */
@Getter
@Setter
public class Battle implements SingleName, Serializable {

    /**
     * 名称
     */
    private String name;

    /**
     * 战斗加成
     */
    private final Fight addition;

    /**
     * 人物信息
     */
    private final BattlePerson<?> person;

    /**
     * 位置
     */
    private final AbstractPosition position;

    /**
     * 人物布局
     */
    private final BattleLayout layout;

    /**
     * 敌人信息
     */
    private BattlePerson<?> enemy;

    /**
     * 战斗中
     */
    private Boolean flight;

    private AttackTimerTask attackTimerTask;

    public Battle() {
        this.name = UUID.fastUUID().toString(true);
        this.addition = null;
        this.person = null;
        this.position = AbstractPosition.defaultPosition();
        this.layout = new BattleLayout();
        this.flight = false;
    }

    public Battle(@NotNull Fight addition, @NotNull BattlePerson<?> person, @NotEmpty BattleLayout layout) {
        this.name = person.getBase().getName();
        this.addition = addition;
        this.person = person;
        this.position = layout.get(person);
        this.layout = layout;
        this.flight = false;
    }

    public boolean hadEnemy() {
        return null != this.enemy;
    }

    public void autoFindEnemy() {
        this.enemy = this.isExistNearestEnemy().map(Map.Entry::getKey).orElse(null);
    }

    public Optional<Map.Entry<BattlePerson<?>, AbstractPosition>> isExistNearestEnemy() {
        return layout.entrySet().stream()
                .filter(entry -> !entry.getKey().checkHostile(this.person))
                .min(Comparator.comparingDouble(entry -> DijkstraUtil.calWeight(this.position, entry.getValue(), this.person.getBase().getSpeed())));
    }

    public Optional<Map.Entry<BattlePerson<?>, AbstractPosition>> isExistNearestFriend() {
        return layout.entrySet().stream()
                .filter(entry -> entry.getKey().checkHostile(this.person))
                .min(Comparator.comparingDouble(entry -> DijkstraUtil.calWeight(this.position, entry.getValue(), this.person.getBase().getSpeed())));
    }

    public BattlePerson<?> nearestFriend() {
        return this.isExistNearestFriend().map(Map.Entry::getKey).orElseThrow(() -> new RuntimeException(RCodeEnum.RUN_ERROR.getMessage()));
    }

    public Optional<Map.Entry<BattlePerson<?>, AbstractPosition>> isExistFrontFriend(double slope) {
        return layout.entrySet().stream()
                .filter(entry -> entry.getKey().checkHostile(this.person))
                .min(Comparator.comparingDouble(entry -> {
                    // 不同斜率的忽略（不同的行军方向）
                    if (slope != DijkstraUtil.calSlope(this.position, entry.getValue()).slope()) {
                        return Double.MAX_VALUE;
                    }
                    return DijkstraUtil.calWeight(this.position, entry.getValue(), this.person.getBase().getSpeed());
                }));
    }

    @Override
    public String getEntityName() {
        return "战斗-个人版";
    }
}
